#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

// 内存池结构
typedef struct {
    char *base;          // 内存池起始地址
    size_t size;         // 内存池总大小
    size_t used;         // 已使用大小
    pthread_mutex_t lock;// 互斥锁
} MemoryPool;

// 服务器配置结构
typedef struct {
    int port;            // 监听端口
    int worker_processes;// 工作进程数
    char *root;          // 网站根目录
    char *proxy_pass;    // 代理转发地址
} ServerConfig;

// 连接结构
typedef struct {
    int fd;              // 连接套接字
    struct sockaddr_in addr; // 客户端地址
    char buffer[4096];   // 数据缓冲区
    ssize_t buffer_len;  // 缓冲区数据长度
} Connection;

// 全局变量
static int listen_fd = -1;
static int epoll_fd = -1;
static ServerConfig config;
static MemoryPool *pool = NULL;
static int *worker_pids = NULL;
static int is_running = 1;

// 内存池初始化
MemoryPool* mem_pool_init(size_t size) {
    MemoryPool *p = (MemoryPool*)malloc(sizeof(MemoryPool));
    if (!p) return NULL;
    
    p->base = (char*)malloc(size);
    if (!p->base) {
        free(p);
        return NULL;
    }
    
    p->size = size;
    p->used = 0;
    pthread_mutex_init(&p->lock, NULL);
    
    return p;
}

// 从内存池分配内存
void* mem_alloc(MemoryPool *pool, size_t size) {
    if (!pool || size <= 0 || pool->used + size > pool->size) {
        return NULL;
    }
    
    pthread_mutex_lock(&pool->lock);
    void *ptr = pool->base + pool->used;
    pool->used += size;
    pthread_mutex_unlock(&pool->lock);
    
    return ptr;
}

// 重置内存池
void mem_pool_reset(MemoryPool *pool) {
    if (pool) {
        pthread_mutex_lock(&pool->lock);
        pool->used = 0;
        pthread_mutex_unlock(&pool->lock);
    }
}

// 销毁内存池
void mem_pool_destroy(MemoryPool *pool) {
    if (pool) {
        free(pool->base);
        pthread_mutex_destroy(&pool->lock);
        free(pool);
    }
}

// 读取配置文件
int read_config(const char *filename, ServerConfig *config) {
    // 简化版：尝试打开配置文件，如失败则使用默认配置
    FILE *fp = fopen(filename, "r");
    if (!fp) {
        // 使用默认配置
        config->port = 8080;
        config->worker_processes = 4;
        config->root = strdup("/var/www/html");
        config->proxy_pass = NULL;
        
        printf("Using default configuration (could not open config file):\n");
    } else {
        // 简单解析配置文件
        char line[256];
        config->port = 8080;
        config->worker_processes = 4;
        config->root = strdup("/var/www/html");
        config->proxy_pass = NULL;
        
        while (fgets(line, sizeof(line), fp)) {
            if (line[0] == '#' || line[0] == '\n') continue;
            
            int port;
            if (sscanf(line, "port %d", &port) == 1) {
                config->port = port;
            } else if (sscanf(line, "worker_processes %d", &config->worker_processes) == 1) {
                // 已获取worker_processes
            } else if (strstr(line, "root") == line) {
                char root[256];
                if (sscanf(line, "root %s", root) == 1) {
                    free(config->root);
                    config->root = strdup(root);
                }
            } else if (strstr(line, "proxy_pass") == line) {
                char proxy[256];
                if (sscanf(line, "proxy_pass %s", proxy) == 1) {
                    config->proxy_pass = strdup(proxy);
                }
            }
        }
        fclose(fp);
        printf("Loaded configuration from %s:\n", filename);
    }
    
    printf("  port: %d\n", config->port);
    printf("  worker processes: %d\n", config->worker_processes);
    printf("  root directory: %s\n", config->root);
    if (config->proxy_pass) {
        printf("  proxy pass: %s\n", config->proxy_pass);
    }
    
    return 0;
}

// 设置非阻塞模式
int set_nonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1) return -1;
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

// 创建监听套接字
int create_listen_socket(int port) {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1) {
        perror("socket");
        return -1;
    }
    
    // 设置SO_REUSEADDR选项
    int reuse = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
        perror("setsockopt");
        close(fd);
        return -1;
    }
    
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    
    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind");
        close(fd);
        return -1;
    }
    
    if (listen(fd, 1024) == -1) {
        perror("listen");
        close(fd);
        return -1;
    }
    
    return fd;
}

// 发送HTTP错误响应
void send_error(int fd, int status_code, const char *message) {
    char response[1024];
    snprintf(response, sizeof(response),
             "HTTP/1.1 %d %s\r\n"
             "Content-Type: text/html\r\n"
             "Content-Length: %lu\r\n"
             "\r\n"
             "<html><body><h1>%d %s</h1></body></html>",
             status_code, message,
             strlen(message) + 24,  // 简单计算内容长度
             status_code, message);
    
    send(fd, response, strlen(response), 0);
}

// 发送文件内容
void send_file(int fd, const char *path) {
    // 尝试打开文件
    int file_fd = open(path, O_RDONLY);
    if (file_fd == -1) {
        send_error(fd, 404, "Not Found");
        return;
    }
    
    // 获取文件信息
    struct stat st;
    if (fstat(file_fd, &st) == -1) {
        close(file_fd);
        send_error(fd, 500, "Internal Server Error");
        return;
    }
    
    // 判断是否为目录
    if (S_ISDIR(st.st_mode)) {
        // 尝试查找目录中的index.html
        char index_path[1024];
        snprintf(index_path, sizeof(index_path), "%s/index.html", path);
        close(file_fd);
        
        file_fd = open(index_path, O_RDONLY);
        if (file_fd == -1) {
            send_error(fd, 403, "Forbidden");
            return;
        }
        
        if (fstat(file_fd, &st) == -1) {
            close(file_fd);
            send_error(fd, 500, "Internal Server Error");
            return;
        }
    }
    
    // 映射文件到内存
    void *file_data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, file_fd, 0);
    close(file_fd);
    
    if (file_data == MAP_FAILED) {
        send_error(fd, 500, "Internal Server Error");
        return;
    }
    
    // 发送HTTP响应头
    char header[512];
    snprintf(header, sizeof(header),
             "HTTP/1.1 200 OK\r\n"
             "Content-Type: text/html\r\n"
             "Content-Length: %ld\r\n"
             "\r\n",
             st.st_size);
    
    send(fd, header, strlen(header), 0);
    // 发送文件内容
    send(fd, file_data, st.st_size, 0);
    
    // 解除映射
    munmap(file_data, st.st_size);
}

// 处理客户端请求
void handle_request(Connection *conn) {
    // 解析HTTP请求
    char method[16], path[1024], version[16];
    if (sscanf(conn->buffer, "%s %s %s", method, path, version) != 3) {
        send_error(conn->fd, 400, "Bad Request");
        return;
    }
    
    // 构建文件路径
    char full_path[1024];
    if (strcmp(path, "/") == 0) {
        snprintf(full_path, sizeof(full_path), "%s/index.html", config.root);
    } else {
        snprintf(full_path, sizeof(full_path), "%s%s", config.root, path);
    }
    
    // 发送文件
    send_file(conn->fd, full_path);
}

// 转发请求到后端服务器
void proxy_request(Connection *conn, const char *backend) {
    // 解析后端服务器地址和端口
    char host[256];
    int port = 80;
    if (sscanf(backend, "%255[^:]:%d", host, &port) != 2) {
        // 如果没有指定端口，使用默认80
        strncpy(host, backend, sizeof(host)-1);
        port = 80;
    }
    
    // 创建到后端的连接
    int backend_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (backend_fd == -1) {
        perror("proxy socket");
        send_error(conn->fd, 502, "Bad Gateway");
        return;
    }
    
    struct sockaddr_in backend_addr;
    memset(&backend_addr, 0, sizeof(backend_addr));
    backend_addr.sin_family = AF_INET;
    backend_addr.sin_port = htons(port);
    
    // 解析主机名或IP地址
    if (inet_pton(AF_INET, host, &backend_addr.sin_addr) <= 0) {
        // 如果不是IP地址，尝试通过域名解析
        struct hostent *he = gethostbyname(host);
        if (!he) {
            herror("gethostbyname");
            close(backend_fd);
            send_error(conn->fd, 502, "Bad Gateway");
            return;
        }
        memcpy(&backend_addr.sin_addr, he->h_addr, he->h_length);
    }
    
    if (connect(backend_fd, (struct sockaddr*)&backend_addr, sizeof(backend_addr)) == -1) {
        perror("connect to backend");
        close(backend_fd);
        send_error(conn->fd, 502, "Bad Gateway");
        return;
    }
    
    // 发送客户端请求到后端
    send(backend_fd, conn->buffer, conn->buffer_len, 0);
    
    // 从后端接收响应并发送给客户端
    char buffer[4096];
    ssize_t n;
    while ((n = recv(backend_fd, buffer, sizeof(buffer), 0)) > 0) {
        send(conn->fd, buffer, n, 0);
    }
    
    close(backend_fd);
}

// 工作进程处理循环
void worker_process_loop() {
    struct epoll_event events[1024];
    
    while (is_running) {
        int nfds = epoll_wait(epoll_fd, events, 1024, -1);
        if (nfds == -1) {
            if (errno == EINTR) continue; // 被信号中断，继续等待
            perror("epoll_wait");
            break;
        }
        
        for (int i = 0; i < nfds; i++) {
            if (events[i].data.fd == listen_fd) {
                // 处理新连接
                struct sockaddr_in client_addr;
                socklen_t client_len = sizeof(client_addr);
                int conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len);
                if (conn_fd == -1) {
                    perror("accept");
                    continue;
                }
                
                set_nonblocking(conn_fd);
                
                struct epoll_event ev;
                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = conn_fd;
                
                if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) == -1) {
                    perror("epoll_ctl: conn_fd");
                    close(conn_fd);
                    continue;
                }
                
                printf("Worker %d: New connection from %s:%d\n", 
                       getpid(), inet_ntoa(client_addr.sin_addr), 
                       ntohs(client_addr.sin_port));
            } else {
                // 处理已有连接的数据
                int fd = events[i].data.fd;
                Connection *conn = (Connection*)mem_alloc(pool, sizeof(Connection));
                if (!conn) {
                    close(fd);
                    continue;
                }
                
                conn->fd = fd;
                conn->buffer_len = recv(fd, conn->buffer, sizeof(conn->buffer) - 1, 0);
                
                if (conn->buffer_len <= 0) {
                    // 连接关闭或出错
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
                    close(fd);
                    printf("Worker %d: Connection closed\n", getpid());
                } else {
                    // 处理请求
                    conn->buffer[conn->buffer_len] = '\0';
                    printf("Worker %d: Received: %.*s\n", getpid(), 
                           (int)conn->buffer_len > 100 ? 100 : (int)conn->buffer_len, 
                           conn->buffer);
                    
                    if (config.proxy_pass) {
                        proxy_request(conn, config.proxy_pass);
                    } else {
                        handle_request(conn);
                    }
                    
                    // 处理完请求后关闭连接（简化处理，实际应支持长连接）
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
                    close(fd);
                }
                
                // 重置内存池（实际实现中应该更精细地管理内存）
                mem_pool_reset(pool);
            }
        }
    }
}

// 信号处理函数
void handle_signal(int sig) {
    switch (sig) {
        case SIGINT:
        case SIGTERM:
            is_running = 0;
            break;
        case SIGCHLD:
            // 处理子进程退出
            while (waitpid(-1, NULL, WNOHANG) > 0);
            break;
    }
}

// 初始化信号处理
void init_signals() {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handle_signal;
    
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGCHLD, &sa, NULL);
    
    // 忽略管道信号
    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, NULL);
}

// 启动工作进程
void start_worker_processes(int num) {
    worker_pids = (int*)malloc(sizeof(int) * num);
    if (!worker_pids) {
        perror("malloc worker_pids");
        exit(EXIT_FAILURE);
    }
    
    for (int i = 0; i < num; i++) {
        pid_t pid = fork();
        if (pid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        } else if (pid == 0) {
            // 子进程（工作进程）
            printf("Worker process %d started\n", getpid());
            worker_process_loop();
            exit(EXIT_SUCCESS);
        } else {
            // 主进程
            worker_pids[i] = pid;
        }
    }
}

// 主函数
int main(int argc, char *argv[]) {
    // 初始化信号处理
    init_signals();
    
    // 读取配置文件，默认使用nginx.conf
    const char *config_file = "nginx.conf";
    if (argc > 1) {
        config_file = argv[1];
    }
    read_config(config_file, &config);
    
    // 初始化内存池
    pool = mem_pool_init(1024 * 1024); // 1MB内存池
    if (!pool) {
        perror("mem_pool_init");
        return 1;
    }
    
    // 创建监听套接字
    listen_fd = create_listen_socket(config.port);
    if (listen_fd == -1) {
        mem_pool_destroy(pool);
        return 1;
    }
    
    // 设置监听套接字为非阻塞
    if (set_nonblocking(listen_fd) == -1) {
        perror("set_nonblocking");
        close(listen_fd);
        mem_pool_destroy(pool);
        return 1;
    }
    
    // 创建epoll实例
    epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        perror("epoll_create1");
        close(listen_fd);
        mem_pool_destroy(pool);
        return 1;
    }
    
    // 将监听套接字添加到epoll
    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = listen_fd;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) {
        perror("epoll_ctl: listen_fd");
        close(epoll_fd);
        close(listen_fd);
        mem_pool_destroy(pool);
        return 1;
    }
    
    printf("Master process %d started, listening on port %d\n", getpid(), config.port);
    
    // 启动工作进程
    start_worker_processes(config.worker_processes);
    
    // 主进程等待信号
    while (is_running) {
        pause();
    }
    
    // 停止工作进程
    printf("\nStopping worker processes...\n");
    for (int i = 0; i < config.worker_processes; i++) {
        if (worker_pids[i] > 0) {
            kill(worker_pids[i], SIGTERM);
            waitpid(worker_pids[i], NULL, 0);
            printf("Worker process %d stopped\n", worker_pids[i]);
        }
    }
    
    // 清理资源
    free(worker_pids);
    close(epoll_fd);
    close(listen_fd);
    mem_pool_destroy(pool);
    free(config.root);
    if (config.proxy_pass) free(config.proxy_pass);
    
    printf("Master process %d stopped\n", getpid());
    return 0;
}
